#include "volume_chart.h"
#include <algorithm>
#include <numeric>
#include <vector>
#include <iostream>
#include <map>
#include "mouse_pos.h"

// 静态变量
static std::vector<StockData> volumeData;
static std::string currentStartDate;
static std::string currentEndDate;
static double maxVolume = 0.0;
static double minVolume = 0.0;
static double averageVolume = 0.0;
static std::vector<float> volumeMA60;  // 60日量能线数据
static std::vector<float> volumeMA4;   // 4日量能线数据
static std::map<std::string,size_t> g_arr_index;
static bool g_isLargeVolumeWashout = false;
static bool g_isLargeVolumeSellout = false;

// 根据结束日期取下标
size_t getDateIndex();

// 计算移动平均线
std::vector<float> calculateVolumeMA(int period) {
    std::vector<float> ma;
    if (volumeData.empty() || period <= 0) return ma;
    size_t end_index = getDateIndex();
    size_t i = end_index-90+1;
    if(int(end_index)-90+1<0)
    {
        i = 0;
    }
    //std::cout<<"坐标范围:"<< i<<" ~ " << end_index <<std::endl;
    for (; i <= end_index; ++i) {
        if (i < period - 1) {
            ma.push_back(0.0f);  // 不足周期的数据填充0
            continue;
        }

        float sum = 0.0f;
        for (int j = 0; j < period; ++j) {
            if(i-j<0)break;
            sum += volumeData[i - j].vol;
        }
        ma.push_back(sum / period);
    }
    // std::cout<<"#49 ma.size():"<< ma.size()<<std::endl;
    return ma;
}

// 获取指定日期范围内的数据
std::vector<StockData> getDataInRange() {
    if (currentStartDate.empty() || currentEndDate.empty()) {
        return volumeData;  // 如果没有设置日期范围，返回所有数据
    }

    // std::vector<StockData> filteredData;
    size_t end_index = getDateIndex();
    size_t startIndex = end_index>=90? end_index - 90:0;
    size_t total_size = volumeData.size();
    if(startIndex>total_size||total_size<end_index)
    {
        // std::cout<<"#64 越界  volumeData.size():"<<volumeData.size()<<",\tstart:"<< startIndex<<",\tend:"<<end_index <<std::endl;
        return volumeData;
    }
    std::vector<StockData> newVector(volumeData.begin() + startIndex, volumeData.begin() + end_index);
    return newVector;

    // // // 按日期范围筛选
    // // for (const auto& data : volumeData) {
    // //     if (data.trade_date >= currentStartDate && data.trade_date <= currentEndDate) {
    // //         filteredData.push_back(data);
    // //     }
    // // }
    
    // // // 如果数据超过90天，只保留最近90天的数据
    // // if (filteredData.size() > 90) {
    // //     filteredData.erase(filteredData.begin(), filteredData.end() - 90);
    // // }
    // return filteredData;
}

// // 获取用于计算均线的数据范围
// std::vector<StockData> getDataInRangeForMA(int period) {
//     if (currentStartDate.empty() || currentEndDate.empty()) {
//         return volumeData;
//     }

//     std::vector<StockData> filteredData;
//     // 按日期范围筛选，多取period天的数据用于计算均线
//     for (const auto& data : volumeData) {
//         if (data.trade_date >= currentStartDate && data.trade_date <= currentEndDate) {
//             filteredData.push_back(data);
//         }
//     }
    
//     // 如果数据超过90+period天，只保留最近90+period天的数据
//     if (filteredData.size() > 90 + period) {
//         filteredData.erase(filteredData.begin(), filteredData.end() - (90 + period));
//     }
//     return filteredData;
// }

// 更新成交量统计数据
void updateVolumeStats(const std::vector<StockData>& data) {
    if (data.empty()) {
        maxVolume = 0.0;
        minVolume = 0.0;
        averageVolume = 0.0;
        return;
    }

    // 计算最大成交量
    maxVolume = std::max_element(data.begin(), data.end(),
        [](const StockData& a, const StockData& b) {
            return a.vol < b.vol;
        })->vol;

    // 计算最小成交量
    minVolume = std::min_element(data.begin(), data.end(),
        [](const StockData& a, const StockData& b) {
            return a.vol < b.vol;
        })->vol;

    // 计算平均成交量
    double totalVolume = std::accumulate(data.begin(), data.end(), 0.0,
        [](double sum, const StockData& data) {
            return sum + data.vol;
        });
    averageVolume = totalVolume / data.size();
}

// 初始化成交量图表
VOLUME_API void initVolumeChart() {
    volumeData.clear();
    currentStartDate.clear();
    currentEndDate.clear();
    maxVolume = 0.0;
    minVolume = 0.0;
    averageVolume = 0.0;
    volumeMA60.clear();
    volumeMA4.clear();
}

// 初始化索引
void initIndexMap(){
    for(size_t i=0;i<volumeData.size();i++)
    {
        const StockData &_data = volumeData[i];
        g_arr_index[_data.trade_date] = i;
    }// END for
}

// 从索引表中取下标
size_t getDateIndex()
{
    // 取下标:
    auto it_end = g_arr_index.lower_bound(currentEndDate);
    if(g_arr_index.end()==it_end)
    {
        // 估计是在数据最后一天之后
        auto iter_right = g_arr_index.rbegin();
        const std::string &str_date_last = iter_right->first;
        if(currentEndDate>str_date_last)
        {
            return g_arr_index.size()-1;
        }
        return 0;
    }
    if(!g_arr_index.contains(currentEndDate))
    {
        --it_end;
    }
    size_t endIndex = it_end->second;
    return endIndex;
}

// 设置K线数据
VOLUME_API void setVolumeData(const std::vector<StockData>& data) {
    // std::cout<<"#182 volume赋值:"<<std::endl;
    volumeData = data;
    auto rangeData = getDataInRange();
    updateVolumeStats(rangeData);
    // 初始化下标:
    initIndexMap();
}

// // 当天是否有K线数据 后来, 没用到, 去判断有没有K线数据用数组的最后一天数据去比对日期就行
// VOLUME_API bool hasKLineByDate(const char* date) {
//     //, StockData* klineData 目前不需要返回值
//     if (!date || !klineData || kLineData.empty()) {
//         return false;
//     }
//     // 查找指定日期的K线数据
//     auto it = std::find_if(volumeData.begin(), volumeData.end(),
//         [date](const StockData& data) {
//             return data.trade_date == date;
//         });
//     if (it != kLineData.end()) {
//         // 找到指定日期的数据，复制到输出参数
//         // *klineData = *it;
//         return true;
//     }
//     return false;
// }

// 设置日期范围
VOLUME_API void setDateRangeVolume(const std::string& startDate, const std::string& endDate) {
    currentStartDate = startDate;
    currentEndDate = endDate;
    auto rangeData = getDataInRange();
    updateVolumeStats(rangeData);
    
    // 计算60日量能线
    // auto rangeDataForMA60 = getDataInRangeForMA(60);
    volumeMA60 = calculateVolumeMA(60);
    
    // 计算4日量能线
    //auto rangeDataForMA4 = getDataInRangeForMA(4);
    volumeMA4 = calculateVolumeMA(4);

    g_isLargeVolumeWashout = false;
    g_isLargeVolumeSellout = false;
    // 判断是放巨量洗盘
    if(volumeMA60.size()>0 && maxVolume>0)
    {
        if(0!=volumeMA60.back())
        {
            // std::cout << "#146 maxVolume: " << maxVolume << " volumeMA60.back(): " << volumeMA60.back() << std::endl;
            const auto& data = rangeData.back();
            if(data.trade_date==currentEndDate)
            {
                if(data.close >= data.open)
                {
                    g_isLargeVolumeWashout = bool(data.vol > volumeMA60.back()*2);
                }
                else if (data.open > data.close)
                {
                    g_isLargeVolumeSellout = bool(data.vol > volumeMA60.back()*1.5);
                }
            }
        }
    }
}

void drawLine(ImDrawList* drawList, const std::vector<float>& data, ImVec2 pos, ImVec2 size,ImU32 color)
{
    // 计算柱状图宽度和间距
    float barWidth = size.x / data.size() * 0.8f;
    float spacing = size.x / data.size() * 0.2f;

    for (size_t i = 1; i < data.size(); ++i) {
        if (data[i] == 0.0f) continue;  // 跳过无效数据

        float x = pos.x + (i ) * (barWidth + spacing);
        float height = (data[i] / maxVolume) * size.y;
        float y = pos.y + size.y - height;

        {
            float prevX = pos.x + (i  - 1) * (barWidth + spacing);
            float prevHeight = (data[i - 1] / maxVolume) * size.y;
            float prevY = pos.y + size.y - prevHeight;
            drawList->AddLine(ImVec2(prevX, prevY), ImVec2(x, y), color);
        }
    }
}

// 绘制成交量图表
VOLUME_API void drawVolumeChart(ImDrawList* drawList, ImVec2 pos, ImVec2 size) {
    if (volumeData.empty() || maxVolume <= 0) {
        return;
    }

    auto rangeData = getDataInRange();
    if (rangeData.empty()) {
        return;
    }

    // 计算柱状图宽度和间距
    float barWidth = size.x / rangeData.size() * 0.8f;
    float spacing = size.x / rangeData.size() * 0.2f;

    // 绘制成交量柱状图
    for (size_t i = 0; i < rangeData.size(); ++i) {
        const auto& data = rangeData[i];
        float x = pos.x + i * (barWidth + spacing);
        
        // 计算柱状图高度
        float height = (data.vol / maxVolume) * size.y;
        
        // 根据涨跌设置颜色
        ImU32 color = (data.close >= data.open) ? 
            IM_COL32(100, 0, 0, 255) :  // 红色表示上涨
            IM_COL32(0, 100, 0, 255);   // 绿色表示下跌

        // 绘制柱状图
        drawList->AddRectFilled(
            ImVec2(x, pos.y + size.y - height),
            ImVec2(x + barWidth, pos.y + size.y),
            color
        );
    }

    // 绘制4日量能线
    drawLine(drawList,volumeMA4, pos,size, IM_COL32(255, 255, 0, 255));

    // 绘制60日量能线
    drawLine(drawList,volumeMA60, pos,size, IM_COL32(150, 150, 150, 255));

    // 绘制成交量统计信息
    char statsText[128];
    snprintf(statsText, sizeof(statsText), 
        "最大: %.0f, 最小: %.0f, 平均: %.0f",
        maxVolume, minVolume, averageVolume);
    drawList->AddText(
        ImVec2(pos.x, pos.y - 20),
        IM_COL32(255, 255, 255, 255),
        statsText
    );
    
    // 鼠标坐标:
    int mousePosX = getMousePosX();
    int mousePosY = getMousePosY();
    drawList->AddLine(ImVec2(mousePosX-9990, mousePosY), ImVec2(mousePosX+9990, mousePosY), ImColor(111, 111, 111));
    drawList->AddLine(ImVec2(mousePosX,mousePosY -9999), ImVec2(mousePosX,mousePosY +9999), ImColor(111, 111, 111));
}

// 获取指定日期范围内的最大成交量
VOLUME_API double getMaxVolume() {
    return maxVolume;
}

// 获取指定日期范围内的最小成交量
VOLUME_API double getMinVolume() {
    return minVolume;
}

// 获取指定日期范围内的平均成交量
VOLUME_API double getAverageVolume() {
    return averageVolume;
} 

// 判断是放巨量洗盘
VOLUME_API bool isLargeVolumeWashout()
{
    return g_isLargeVolumeWashout;
}


// 判断是巨量出货
VOLUME_API bool isLargeVolumeSellout()
{
    return g_isLargeVolumeSellout;
}

/*
成交量算法的视频
https://www.bilibili.com/video/BV1Qc411k7V2
讲到大幅上涨前会有小幅上涨:
https://www.bilibili.com/video/BV1D5yrYSERm
量价关系教学:
https://www.bilibili.com/video/BV1yS1tYGE2j
    "卖方力量消耗殆尽"
红肥绿瘦:
https://www.bilibili.com/video/BV1JK1gYUEbX



*/